package com.pcbly.web.components.utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.Callable;

@SuppressWarnings("unchecked")
public class InputOutputStreamUtils implements Callable {
	private static final int DEFAULT_BUFFER_SIZE = 8000;
	private long amountWritten;
	private final int bufferSize;
	private final InputStream in;
	private final OutputStream outs[];
	private final boolean closeStreamsOnCompletion;

	public InputOutputStreamUtils(int bufferSize,
			boolean closeStreamsOnCompletion, InputStream in,
			OutputStream outputStreams[]) {
		amountWritten = 0L;
		if (bufferSize <= 0)
			bufferSize = DEFAULT_BUFFER_SIZE;
		this.bufferSize = bufferSize;
		this.closeStreamsOnCompletion = closeStreamsOnCompletion;
		this.in = in;
		outs = outputStreams;
	}

	public InputOutputStreamUtils(int bufferSize, InputStream in,
			OutputStream outputStreams[]) {
		this(bufferSize, false, in, outputStreams);
	}

	public InputOutputStreamUtils(InputStream in, OutputStream outputStreams[]) {
		this(DEFAULT_BUFFER_SIZE, in, outputStreams);
	}

	public InputOutputStreamUtils(boolean closeStreamsOnCompletion,
			InputStream in, OutputStream outputStreams[]) {
		this(DEFAULT_BUFFER_SIZE, closeStreamsOnCompletion, in, outputStreams);
	}

	public Object call() throws Exception {
		return Long.valueOf(doWrap());
	}

	public long doWrap() throws IOException {
		byte b[] = new byte[bufferSize];
		int count = 0;
		amountWritten = 0L;
		OutputStream arr$[];
		int len$;
		do {
			arr$ = outs;
			len$ = arr$.length;
			for (int i$ = 0; i$ < len$; i$++) {
				OutputStream out = arr$[i$];
				out.write(b, 0, count);
			}

			amountWritten += count;
			count = in.read(b);
		} while (count >= 0);
		arr$ = outs;
		len$ = arr$.length;
		for (int i$ = 0; i$ < len$; i$++) {
			OutputStream out = arr$[i$];
			out.flush();
		}

		if (closeStreamsOnCompletion)
			try {
				closeStreams();
			} catch (IOException ioe) {
			}
		return amountWritten;
	}

	public InputOutputStreamUtils closeStreams() throws IOException {
		try {
			in.close();
		} finally {
			OutputStream arr$[] = outs;
			int len$ = arr$.length;
			for (int i$ = 0; i$ < len$; i$++) {
				OutputStream out = arr$[i$];
				try {
					out.close();
				} catch (IOException ioe) {
				}
			}

		}
		return this;
	}

	public long getAmountWritten() {
		return amountWritten;
	}

}
